<?php
namespace Database;

class Base
{

    use \CommonTrait\Base;

    private $model = '';

    private $pdo = null;

    public function setModel($model)
    {
        $this->model = $model;
    }

    public function getModel()
    {
        if(is_string($this->model)){
            return $this->get($this->model);
        }
        return $this->model;
    }

    public function getTable()
    {
        return $this->getModel()->getTable();
    }

    public function getPdo()
    {
        if($this->pdo){
            return $this->pdo;
        }
        $this->pdo = $this->get(CORE_PDO)->get($this->getModel()->getConfig());
        return $this->pdo;
    }

    public function setPdo($pdo)
    {
        return $this->pdo = $pdo;
    }

    public function beginTransaction()
    {
        return $this->getPdo()->beginTransaction();
    }

    public function commit()
    {
        return $this->getPdo()->commit();
    }

    public function rollBack()
    {
        return $this->getPdo()->rollBack();
    }

    public function getSql()
    {
        return $this->get(CORE_SQL);
    }

    private function common($data, $type = '')
    {
        if(is_string($data)){
            $data = [
                'sql' => $data,
                'placeholder' => []
            ];
        }
        $pdo = $this->getPdo();
        $sm = $pdo->prepare($data['sql']);
        foreach($data['placeholder'] as $k => $v){
            $sm->bindValue($k, $v);
        }
        $sm->execute();
        if($type == 'fetch'){
            return $sm->fetch();
        }
        else if($type == 'fetchAll'){
            return $sm->fetchAll();
        }
        else if($type == 'fetchColumn'){
            return $sm->fetchColumn();
        }
        else if($type == 'runInsert'){
            return $pdo->lastInsertId();
        }
        else if($type == 'runUpdate'){
            return $sm->rowCount();
        }
        else if($type == 'runDelete'){
            return $sm->rowCount();
        }
        else if($type == 'runExecute'){
            return true;
        }
    }

    public function fetch($data)
    {
        return $this->common($data, 'fetch');
    }

    public function fetchAll($data)
    {
        return $this->common($data, 'fetchAll');
    }

    public function fetchColumn($data)
    {
        return $this->common($data, 'fetchColumn');
    }

    public function runInsert($data)
    {
        return $this->common($data, 'runInsert');
    }

    public function runUpdate($data)
    {
        return $this->common($data, 'runUpdate');
    }

    public function runDelete($data)
    {
        return $this->common($data, 'runDelete');
    }

    public function runExecute($data)
    {
        return $this->common($data, 'runExecute');
    }

    public function insert($data)
    {
        $sql = $this->getSql();
        $sql->table($this->getTable());
        foreach($data as $k => $v){
            $sql->set($k, $v);
        }
        return $this->runInsert($sql->getInsertSql());
    }

    public function update($data, $id, $operate = '=')
    {
        $sql = $this->getSql();
        $sql->table($this->getTable());
        foreach($data as $k => $v){
            $sql->set($k, $v);
        }
        $sql->where('id', $operate, $id);
        return $this->runUpdate($sql->getUpdateSql());
    }

    public function updateMore($data, $id)
    {
        return $this->update($data, $id, 'in');
    }

    public function one($id)
    {
        $sql = $this->getSql();
        $sql->table($this->getTable());
        $sql->where('id', '=', $id);
        $sql->setPage(1);
        $sql->setPageSize(1);
        $sql->setLimit();
        return $this->fetch($sql->get());
    }

    public function more($idIn = '')
    {
        $sql = $this->getSql();
        $sql->table($this->getTable());
        $sql->where('id', 'in', $idIn);
        $sql->setOrderRaw("field(id,{$idIn})");
        return $this->fetchAll($sql->get());
    }

    public function delete($idIn)
    {
        $sql = $this->getSql();
        $sql->table($this->getTable());
        $sql->where('id', 'in', $idIn);
        return $this->runDelete($sql->getDeleteSql());
    }

    public function deleteByField($field = '', $value = '')
    {
        $sql = $this->getSql();
        $sql->table($this->getTable());
        $sql->where($field, '=', $value);
        return $this->runDelete($sql->getDeleteSql());
    }

    public function getOneByField($field = '', $value = '')
    {
        $sql = $this->getSql();
        $sql->table($this->getTable());
        $sql->where($field, '=', $value);
        return $this->fetch($sql->get());
    }

    public function getOneByFields($data = [])
    {
        $sql = $this->getSql();
        $sql->table($this->getTable());
        $first = true;
        foreach($data as $field => $value){
            if($first){
                $first = false;
                $sql->where($field, '=', $value);
            }
            else{
                $sql->andWhere($field, '=', $value);
            }
        }
        return $this->fetch($sql->get());
    }

    public function getMoreByField($field = '', $value = '')
    {
        $sql = $this->getSql();
        $sql->table($this->getTable());
        $sql->where($field, '=', $value);
        return $this->fetchAll($sql->get());
    }

    public function getMoreByFields($data = [])
    {
        $sql = $this->getSql();
        $sql->table($this->getTable());
        $first = true;
        foreach($data as $field => $value){
            if($first){
                $first = false;
                $sql->where($field, '=', $value);
            }
            else{
                $sql->andWhere($field, '=', $value);
            }
        }
        return $this->fetchAll($sql->get());
    }

    public function getList($idIn = '')
    {
        $sql = $this->getSql();
        $sql->field('*');
        $sql->table($this->getTable());
        if($idIn != ''){
            $sql->where('id', 'in', $idIn);
        }
        $list = $this->fetchAll($sql->get());
        return $list;
    }

    public function getIndexByOrder($page, $limit, $field, $type)
    {
        $sql = $this->getSql();
        $sql->field('*');
        $sql->table($this->getTable());
        $sql->setPage($page);
        $sql->setPageSize($limit);
        $sql->setLimit();
        $sql->setOrder($field, $type);
        $list = $this->fetchAll($sql->get());
        $count = $this->fetchColumn($sql->getTotalSql());
        return [
            'list' => $list,
            'count' => $count
        ];
    }

    public function setDataSort($sqls = [])
    {
        foreach($sqls as $sql){
            $this->runUpdate($sql);
        }
    }

}